﻿using System;
using System.Security.Principal;
using good1.ApplicationServices.Interface;
using good1.Core;
using SharpArch.Core;
using SharpArch.Core.PersistenceSupport;

namespace good1.ApplicationServices
{
    public class SecurityContextService : ISecurityContextService
    {
        public SecurityContextService(IGoodCookieService goodCookie, ISessionContainer sessionContainer, IRepository<User> userRepository, IAuthenticationService authenticationService)
        {

            Check.Require(userRepository != null, "userRepository may not be null");
            Check.Require(goodCookie != null, "goodCookie may not be null");
            Check.Require(sessionContainer != null, "sessionContainer may not be null");
            Check.Require(authenticationService != null, "authenticationService may not be null");
            this.authenticationService = authenticationService;
            this.sessionContainer = sessionContainer;
            this.goodCookie = goodCookie;
            this.userRepository = userRepository;

        }

        public string UserEmail
        {
            get { return goodCookie.UserEmail; }
            set { goodCookie.UserEmail = value; }
        }

    
        public int? UserId
        {
            get { return goodCookie.UserId; }
            set { goodCookie.UserId = value; }
        }

        public string FriendlyName
        {
            get
            {
                if (string.IsNullOrEmpty(goodCookie.FriendlyName) && !string.IsNullOrEmpty(goodCookie.AuthenticatedName))
                {
                    goodCookie.FriendlyName = authenticationService.GetByUserName(goodCookie.AuthenticatedName).FirstName;
                    if(string.IsNullOrEmpty(goodCookie.FriendlyName)) LogOut();
                }
                return goodCookie.FriendlyName;
            }
            set { goodCookie.FriendlyName = value; }
        }

        public DateTime? LastVisit
        {
            get { return goodCookie.LastVisit; }
            set { goodCookie.LastVisit = value; }
        }

        public void LogIn(string userName, bool rememberMe)
        {
            User user = authenticationService.GetByUserName(userName);
            string roles = authenticationService.GetRolesByUserNameInPipeFormat(userName);
            AuthTicket(userName, roles, rememberMe);
            SetUserDataOnLogin(user.FirstName, user.Id);
        }

        public void LogOut()
        {
            sessionContainer.LogOut();
        }


        private bool InsideHttpPostEvent
        {
            get { return goodCookie.InsideHttpPostEvent; }
            set { goodCookie.InsideHttpPostEvent = value; }
        }

        public void AuthTicket(string username, string roles, bool rememberMe)
        {
            goodCookie.AddAuthenticationCookie(username, rememberMe, roles);
        }

        private void SetUserDataOnLogin(string name, int id)
        {
            InsideHttpPostEvent = true;  //TODO this could probably be done by an internal check within container.
            FriendlyName = name;
            UserId = id;
        }

        //Principal and roles are not put in cookies by default.
        //http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html
        public GenericPrincipal GetPrincipal()
        {
            if (string.IsNullOrEmpty(goodCookie.AuthenticatedName)) return null;
            GenericIdentity userIdentity = new GenericIdentity(goodCookie.AuthenticatedName);
            GenericPrincipal userPrincipal = new GenericPrincipal(userIdentity, goodCookie.AuthenticatedRoles);
            return userPrincipal;
        }

        private readonly IGoodCookieService goodCookie;
        private readonly IAuthenticationService authenticationService;
        private readonly ISessionContainer sessionContainer;
        private readonly IRepository<User> userRepository;
    }
}
